package models

import (
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

type Jhttp struct {
	client http.Client
	header http.Header
	res    *http.Response
	form   *url.Values
	body   *strings.Reader
	err    error
}

type JhttpRet struct {
	StatusCode int
	Msg        string
}

func MakeHttp() *Jhttp {
	return &Jhttp{
		header: make(http.Header),
	}
}

func (h *Jhttp) SetForm(form *url.Values) *Jhttp {
	h.header.Add("Content-Type", "application/x-www-form-urlencoded")
	h.body = strings.NewReader(form.Encode())
	return h
}

func (h *Jhttp) SetJson(body []byte) *Jhttp {
	h.header.Add("Content-Type", "application/json")
	h.body = strings.NewReader(string(body))
	return h
}

func (h *Jhttp) AddHeader(key, value string) *Jhttp {
	h.header.Add(key, value)
	return h
}

func (h *Jhttp) AddFile(uploadName, filePath string) *Jhttp {
	file, err := os.Open(filePath)
	if err != nil {
		panic(err)
	}
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile(uploadName, filepath.Base(filePath))
	if err != nil {
		panic(err)
	}
	_, err = io.Copy(part, file)
	if err != nil {
		panic(err)
	}
	writer.Close()
	h.body = strings.NewReader(body.String())
	h.header.Add("Content-Type", writer.FormDataContentType())

	return h
}

func (h *Jhttp) Get(url string) *Jhttp {
	request, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		h.err = err
		return h
	}
	request.Header = h.header
	//
	res, err := h.client.Do(request)
	if err != nil {
		h.err = err
		return h
	}
	h.res = res
	return h
}

func (h *Jhttp) Post(url string) *Jhttp {
	request, err := http.NewRequest(http.MethodPost, url, nil)
	if err != nil {
		h.err = err
		return h
	}

	if h.body != nil {
		request.ContentLength = int64(h.body.Len())
		request.Body = io.NopCloser(h.body)
	}
	request.Header = h.header

	res, err := h.client.Do(request)
	if err != nil {
		h.err = err
		return h
	}
	h.res = res
	return h
}

func (h *Jhttp) Call(f func(res *http.Response, err error)) {
	f(h.res, h.err)
}

func (h *Jhttp) Ret() JhttpRet {
	var ret = JhttpRet{}

	if h.err != nil {
		ret.Msg = "发生错误 : " + h.err.Error()
	}

	b, err := io.ReadAll(h.res.Body)
	if err != nil {
		ret.Msg = "发生错误 : " + err.Error()
	}
	ret.Msg = string(b)
	ret.StatusCode = h.res.StatusCode
	h.res.Body.Close()
	return ret
}

func (h *Jhttp) ToString() string {
	if h.res == nil {
		return ""
	}
	if h.err != nil {
		return "发生错误 : " + h.err.Error()
	}

	b, err := io.ReadAll(h.res.Body)
	if err != nil {
		return "发生错误 : " + err.Error()
	}
	h.res.Body.Close()
	return string(b)
}
